package com.usooft.metaTalent.core.platform.service.base;

import com.usooft.framework.core.query.Limit;
import com.usooft.framework.core.query.Page;
import com.usooft.metaTalent.core.platform.entity.Article;
import com.usooft.metaTalent.core.platform.mapper.ArticleMapper;
import com.usooft.metaTalent.core.platform.query.ArticleQuery;
import com.usooft.metaTalent.core.platform.service.ArticleService;
import com.usooft.metaTalent.core.platform.wrapper.ArticleWrapper;
import java.lang.Integer;
import java.lang.Long;
import java.lang.Override;
import java.lang.String;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.lang.NonNull;

public abstract class BaseArticleService implements ArticleService {
    @Autowired
    private ArticleMapper articleMapper;

    @Override
    public Article get(@NonNull Long id) {
        return find(id).orElseThrow();
    }

    @Override
    public Optional<Article> find(@NonNull Long id) {
        return Optional.ofNullable(articleMapper.get(id));
    }

    @Override
    public List<ArticleWrapper> list(ArticleQuery query) {
        return articleMapper.list(query);
    }

    @Override
    public Page<ArticleWrapper> page(ArticleQuery query) {
        int rows = articleMapper.count(query.getFilter());
        return new Page<>(rows, rows == 0 ? new ArrayList<>() : articleMapper.list(query));
    }

    protected Optional<Article> findOne(ArticleQuery.Filter filter, ArticleQuery.Sorts sorts) {
        List<ArticleWrapper> wrappers = list(ArticleQuery.builder()
                                .filter(filter)
                                .sorts(sorts)
                                .limit(Limit.rowCount(1))
                                .build());
        return wrappers.stream().findFirst().map(Function.identity());
    }

    protected Optional<Article> findOne(ArticleQuery.Filter filter) {
        return findOne(filter, ArticleQuery.Sorts.builder().build());
    }

    @Override
    public int count(ArticleQuery.Filter filter) {
        return articleMapper.count(filter);
    }

    protected Article internalAdd(String title, String content, String releaseTime,
            Integer pageView, Article.ArticleType articleType, Long clazzId) {
        Article article = new Article();
        article.setTitle(title);
        article.setContent(content);
        article.setReleaseTime(releaseTime);
        article.setPageView(pageView);
        article.setArticleType(articleType);
        article.setClazzId(clazzId);

        article.setCreatedDate(LocalDateTime.now());
        article.setVersion(0);
        article.setState(Article.State.UN_RELEASE);
        article.setIsDelete(false);
        articleMapper.add(article);
        return article;
    }

    protected void internalUpdate(@NonNull Article article) {
        article.setLastModifiedDate(LocalDateTime.now());

        int rows = articleMapper.update(article);
        if (rows == 0) {
            throw new OptimisticLockingFailureException("更新失败。可能文章 (" + article.getId() + ") 的版本 (" + article.getVersion() + ") 已不是最新");
        }
        article.setVersion(article.getVersion() + 1);
    }
}
